unit main;

{$mode Delphi}

interface

uses
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
    Grids, Menus, Math, pnt_edt, area_core, area_pnt, area_trn;

type

    Tfm_main = class(TForm)
        // Виджеты
        ar_draw: TImage;
        ls_pnts: TStringGrid;
        bc_do_solve: TMenuItem;
        bc_do_add_pnt: TMenuItem;
        bc_do_edt_pnt: TMenuItem;
        bc_do_del_pnt: TMenuItem;
        bc_do_del_all: TMenuItem;
        mn_contex: TPopupMenu;
        // Обработчики событий
        procedure bc_do_add_pntClick(Sender: TObject);
        procedure bc_do_del_allClick(Sender: TObject);
        procedure bc_do_del_pntClick(Sender: TObject);
        procedure bc_do_edt_pntClick(Sender: TObject);
        procedure bc_do_solveClick(Sender: TObject);
        procedure FormShow(Sender: TObject);
    private
    public
    end;

var
    fm_main: Tfm_main;
    area: TDArea;

implementation

{$R *.lfm}

// Загрузка формы
procedure Tfm_main.FormShow(Sender: TObject);
begin
    area := TDArea.init(ar_draw);
    area.clear();
end;

// Создание новой точки
procedure Tfm_main.bc_do_add_pntClick(Sender: TObject);
const
    D_VAL = -1.0;
var
    area_pnt_o: TDAPoint;
    area_tmp_o: TDAPoint;
begin
    // Проверка переполнения массива
    if area.pnts_get_cnt = area.pnts_get_cnt_max then
        ShowMessage('Достигнуто максимальное количество точек.')
    else
    begin
        area_tmp_o := TDAPoint.init(D_VAL, D_VAL);
        if fm_pnt_edt.pnts_modify(area_tmp_o) then
        with ls_pnts do
        begin
            area_pnt_o := area.pnts_conv(area_tmp_o);
            RowCount := RowCount + 1;
            Cells[0, RowCount - 1] := IntToStr(RowCount - 1);
            Cells[1, RowCount - 1] := FloatToStr(area_tmp_o.get_rcoord.X);
            Cells[2, RowCount - 1] := FloatToStr(area_tmp_o.get_rcoord.Y);
            area.pnts_add(area_pnt_o);
            area.render_pnt(area_pnt_o);
        end;
    end;
end;

// Редактирование точки
procedure Tfm_main.bc_do_edt_pntClick(Sender: TObject);
var
    area_pnt_o: TDAPoint;
    area_tmp_o: TDAPoint;
begin
    
    if area.pnts_get_cnt = 0 then
    begin
        ShowMessage('Отсутствуют точки для редактирования.');
        exit;
    end;

    with ls_pnts do
    begin
        // Конвертирование координат
        area_pnt_o := area.pnts_get_by_index(ls_pnts.Row - 1);
        area_tmp_o := area.pnts_conv(area_pnt_o);
        // Применение изменений координат
        if fm_pnt_edt.pnts_modify(area_tmp_o) then
        begin
            area_pnt_o := area.pnts_conv(area_tmp_o);
            Cells[1, Row] := FloatToStr(area_tmp_o.get_rcoord.X);
            Cells[2, Row] := FloatToStr(area_tmp_o.get_rcoord.Y);
            area.pnts_insert(area_pnt_o, Row - 1);
            area.pnts_render_all();
        end;
    end;
end;

// Удаление выделенной точки
procedure Tfm_main.bc_do_del_pntClick(Sender: TObject);
var
    I: Integer;
begin
    
    if area.pnts_get_cnt = 0 then
    begin
        ShowMessage('Отсутствуют точки для удаления.');
        exit;
    end;

    with ls_pnts do
    begin
        area.pnts_del_by_index(Row - 1);
        if area.pnts_get_cnt <> 0 then
        begin
            Cells[1, Row] := Cells[1, RowCount - 1];
            Cells[2, Row] := Cells[2, RowCount - 1];
        end;
        area.pnts_render_all();
        RowCount := RowCount - 1;
    end;
end;

// Удаление всех точек
procedure Tfm_main.bc_do_del_allClick(Sender: TObject);
begin
    area.pnts_del_all();
    ls_pnts.RowCount := 1;
end;

// Проверка признака треугольника
function get_trn_prop(head_f, head_s, head_t: TDAPoint) :Boolean;
begin   
    get_trn_prop := ((head_s.get_rcoord.Y - head_f.get_rcoord.Y) * 
                     (head_t.get_rcoord.X - head_f.get_rcoord.X)) <>
                    ((head_t.get_rcoord.Y - head_f.get_rcoord.Y) * 
                     (head_s.get_rcoord.X - head_f.get_rcoord.X))
end;

// Решение задачи
procedure Tfm_main.bc_do_solveClick(Sender: TObject);
var
    I, J, K, L: Integer;
    trn_c: Integer;
    trn_t: TDATriangle;
    trn_m: TDATriangle;
    bis_m: Real;
    bis_t: Real;
    head_f, head_s, head_t: TDAPoint;
begin

    L := area.pnts_get_cnt();
    trn_c := 0;

    if L < 3 then
    begin
        ShowMessage('Для решения задачи требуется более двух точек.');
        exit;
    end;

    for I := 0 to L - 3 do
        for J := I + 1 to L - 2 do
            for K := J + 1 to L - 1 do
            begin

                head_f := area.pnts_get_by_index(I);
                head_s := area.pnts_get_by_index(J);
                head_t := area.pnts_get_by_index(K);

                if not get_trn_prop(head_f, head_s, head_t) then
                    continue;

                trn_t := TDATriangle.init(head_f, head_s, head_t);

                with trn_t do
                    bis_t := get_bisc_len(get_bisc_min);

                if trn_c = 0 then
                begin
                    Inc(trn_c);
                    bis_m := bis_t;
                    trn_m := trn_t;
                    continue;
                end;

                if bis_t < bis_m then
                begin
                    trn_m := trn_t;
                    bis_m := bis_t;  
                end;

            end;

    if trn_c = 0 then
    begin
        ShowMessage('Все треугольники являются вырожденными. Результат отсутствует.');
        exit;
    end;

    with area do
    begin
        clear();
        render_trn_fit(trn_m);
    end;
    
    with trn_m do
    begin
        head_f := area.pnts_conv(get_head_pnt(0));
        head_s := area.pnts_conv(get_head_pnt(1));
        head_t := area.pnts_conv(get_head_pnt(2));
        ShowMessage('Характеристики треугольника с минимальной биссектрисой:' +
        sLineBreak + sLineBreak + 'Вершина #1 (Красная): X = ' +
        FloatToStr(head_f.get_rcoord.X) + ', Y = ' +
        FloatToStr(head_f.get_rcoord.Y) + sLineBreak + 
        'Вершина #2 (Желтая): X = ' + FloatToStr(head_s.get_rcoord.X) + ', Y = ' +
        FloatToStr(head_s.get_rcoord.Y) + sLineBreak +
        'Вершина #3 (Зеленая): X = ' + FloatToStr(head_t.get_rcoord.X) + ', Y = ' +
        FloatToStr(head_t.get_rcoord.Y) + sLineBreak + 'Длина минимальной биссектрисы: ' +
        FloatToStr(bis_m));
    end;
end;

end.

